import json
import random
import re

import django_redis
from django import http
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.http import JsonResponse
from django.shortcuts import render, redirect

# Create your views here.
from django.urls import reverse
from django.views import View

from apps.areas.models import Address
from apps.shoppingcart.utils import merge_cookie_to_redis
from apps.users.utils import LoginRequiredJsonMixin
from utils.response_code import RETCODE
from . import models
from libs.yuntongxun.sms import CCP
from .utils import jiajiemi
#注册
class ZhuceView(View):

    def get(self,request):
        return render(request,'register.html')
    #前段以表单形式发送,后端接收参数，验证
    def post(self,request):
        # 用get不会报错
        username = request.POST.get('user_name')
        password = request.POST.get('pwd')
        password2 = request.POST.get('cpwd')
        mobile = request.POST.get('phone')
        allow = request.POST.get('allow')
        pic_code = request.POST.get('pic_code')
        uuid = request.POST.get('uuida')
        print(request.POST)
#         后端再次检验参数
       # 如果不是 真全部存在,则报错
        if not all([username,password,password2,mobile,allow]):
            return http.HttpResponseForbidden('参数不全哦')
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输入5-20个字符长度的用户名')
        if not re.match(r'^[0-9A-Za-z]{8,20}$',password):
            return http.HttpResponseForbidden('请输入8-20个字符长度的密码')
        if password != password2:
            return http.HttpResponseForbidden('两次输入的密码不一致')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')
        if allow != 'on':
            return http.HttpResponseForbidden('注册前，请勾选用户协议')
        if re.match(r'^\w{4}$',pic_code):
            #如果正则匹配成功， 需要访问数据库查找是否有pic_code=text
            #一句话连接redis服务器
            cli = django_redis.get_redis_connection("verify_image_code")
            text = cli.get("img_%s"% uuid).decode()
            print(text)
            print(pic_code)
            if text != pic_code:
                return http.HttpResponseForbidden('验证码输入有误')

        # 都正确创建用户信息到数据库，如果已经迁移过数据， 则可以有提示
        try:
            models.User.objects.create_user(username=username,password=password,mobile=mobile)

        except Exception:
            return render(request, 'register.html')
        a = models.User.objects.count()
        user = authenticate(username=username,password=password2)
        login(request,user)
        print(user)
        print('恭喜您,迎来新用户目前有%s个用户注册网站会员了！' % a)
        response = redirect(reverse('index'))

        response.set_cookie('username',username, max_age=3600 * 24 * 15)
        return response


#判断用户名是否重复
class UsernameCountView(View):
    #因为是路径传参, 利用ajax来访问 /usernames/(?P<username>[a-zA-Z0-9_-]{5,20})/count/
    def get(self,request,username):
        count = models.User.objects.filter(username=username).count()
        return http.JsonResponse({"count":count})


#判断手机号是否重复
class MobileCountView(View):

    #1axios 会发起get请求拼接此url来，并且通过路径传入一个mobile参数
    def get(self,request,mobile):
        #2根据mobile查找数据库

        count = models.User.objects.filter(mobile=mobile).count()

        #3axios说他需要一个json对象，返回前端前面加http
        return  http.JsonResponse({"count":count})


#前端判断验证码是否正确
class CodetestView(View):

    def get(self,request,uuidq):
        print(uuidq)
        cli = django_redis.get_redis_connection('verify_image_code')
        text = cli.get("img_%s"% uuidq).decode()
        print(text)
        return http.JsonResponse({"text":text})


#发送短信验证码后端接口(注册，传入手机号)
class SMSCodeView(View):

    def get(self, request,mobile):
        #获得验证码和uuid

        code = request.GET.get('code')
        uuid = request.GET.get('uuid')
        #验证 验证码是否正确 ,不正确就返回
        cli = django_redis.get_redis_connection('verify_image_code')
        uuid_value = cli.get("img_%s" % uuid).decode()
        #判断图片是否过期了,过期提示失效
        if uuid_value == None:
            return http.JsonResponse({"code1":"4004",'errmsg':'图形验证码失效'})
        #有值但是不对的时候,是输入有误
        if code.lower() != uuid_value.lower():
            return http.JsonResponse({"code1":"4001",'errmsg':'图片验证码输入有误'})

        #多加一个判断，是否重复发送请求


        #验证码输入正确,开始发送短信
        #随机生成验证码,存入数据库，便于校验
        random_sms = random.randint(1000,9999)
        print('短信验证码:%s'%random_sms)
        #连接三号redis数据库
        sms_cli = django_redis.get_redis_connection('SMS')
        #如果数据库中存在时间标识则返回  ,存在返回1 ,不存在返回0
        count = sms_cli.exists('%s_time_flag' % mobile)

        if count == 1:
            return http.JsonResponse({"code1":"2",'errmsg':'短信发送过于频繁'})
        sms_cli.setex(mobile,300,random_sms)

        #判断下现在有多少人注册了
        num = models.User.objects.count()
        #因为现在只能给自己发..手机号就填自己的
        from celery_tasks.sms.tasks import ccp_send_sms_code
        ccp_send_sms_code.delay('17689949640','%d胡加增欢迎您,恭喜您成为本站第%s个尊贵用户 ' % (random_sms,num+1))
        # CCP().send_template_sms('17689949640',['%d胡加增欢迎您,恭喜您成为本站第%s个尊贵用户 ' % (random_sms,num+1),5],1)
        # 发送成功在数据库多写一个时间的标识 一个手机一个标识, 前面加一个判断如果存在则返回，必须要等时间结束才可以继续注册
        sms_cli.setex('%s_time_flag' % mobile, 300, 1)
        return http.JsonResponse({"code1":"0",'errmsg':'短信发送成功'})


        #

# 根据用户名取出手机号
class SMSCodeView2(View):

    def get(self, request,username):
        #根据username获取手机号
        user = models.User.objects.get(username=username)
        mobile = user.mobile



        #获得验证码和uuid
        code = request.GET.get('code')
        uuid = request.GET.get('uuid')
        #验证 验证码是否正确 ,不正确就返回
        cli = django_redis.get_redis_connection('verify_image_code')
        uuid_value = cli.get("img_%s" % uuid).decode()
        #判断图片是否过期了,过期提示失效
        if uuid_value == None:
            return
        #有值但是不对的时候,是输入有误
        if code.lower() != uuid_value.lower():
            return

        return JsonResponse({'mobile':mobile})




#短信验证接口
class CheckSmsCodeView(View):
    def get(self,request,mobile,sms_code):
        #连接短信3号redis数据库查找是否存在
        check_cli = django_redis.get_redis_connection('SMS')
        mobile_velue = check_cli.get(mobile)
        if mobile_velue == None:
            return http.JsonResponse({'ret':'-1'})
        elif mobile_velue.decode() == sms_code:
            return http.JsonResponse({'ret':'0'})
        else:
            return http.JsonResponse({'ret': '-1'})


#登陆
class LoginView(View):

    def get(self,request):
        #提供登陆界面
        return render(request, 'login.html')

    def post(self,request):

        username = request.POST.get('username')
        password = request.POST.get('pwd')
        remembered = request.POST.get('remembered')
        #是否都传入了
        if not all([username,password]):
            return http.HttpResponse('参数不全')
        #后端校验用户名密码格式
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$',username):
            return http.HttpResponse('用户名输入格式错误')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponse('密码输入格式错误')

        #验证user是否存在即可判断用户名密码是否存在
        user = authenticate(username=username,password=password)
        if not user:
            return http.HttpResponse('用户名或密码错误')
        login(request,user)

        #登陆之后,判断是否记住登陆状态
        if remembered != 'on':
            #0代表浏览器关闭会话结束
            request.session.set_expiry(0)
        else:
            #None为默认两周时间
            request.session.set_expiry(None)

        #重定向到主页
        #需要判断是否是由LoginRequiredMixin跳转过来带有next参数的
        #如果有next ， 则登陆成功会跳转到next参数地址
        if request.GET.get('next'):
            print(request.GET.get('next'))
            response = redirect(request.GET.get('next'))
        else:
            response = redirect(reverse('index'))

        #user.username 可能是手机号  3600秒 24 小时 15天
        #在response加上cookie
        response = merge_cookie_to_redis(request=request,response=response)
        response.set_cookie('username',user.username,3600*24*15)
        return response


#用户退出
class LogoutView(View):
    def get(self,request):
        logout(request)
        #手动清除掉cookie
        response = redirect(reverse('index'))
        response.delete_cookie('username')
        return response



#展示用户中心
class UsercenterView(LoginRequiredMixin,View):
    def get(self,request):

        context = {
            "username":request.user.username,
            'mobile':request.user.mobile,
            'email':request.user.email,
            'email_active':request.user.email_active,
        }
        return render(request,'user_center_info.html',context=context)


#添加邮箱,发送邮件
class EmailView(LoginRequiredJsonMixin,View):
    # LoginRequiredJsonMixin 改写了原本登陆请求混合的错误返回方法，使其返回Json数据
    #继承这个登陆请求混合类，里面能判断是否登陆状态，如果不是则重定向
    def get(self,request,email):

        #后端再次校验邮箱地址
        judge = re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$',email)
        if not judge:
            return http.HttpResponseForbidden('邮箱格式错误')
        # if request.user.email == email:
        #     return http.HttpResponseForbidden('用户已激活')

        #添加邮箱 ,记得要保存和异常处理
        try:
            request.user.email = email
            request.user.save()
            #如果添加成功就发送邮件激活
            from celery_tasks.email import tasks
            #获取当前的用户名和邮箱用于 发送之后的验证是否是同一账号
            data = {"username":request.user.username,"email":email}
            #加密

            scret_data  = jiajiemi().jiami(data)
            #拼接查询参数到url ,当前登陆的用户名
            url = 'http://www.hujiazeng.com:8000/checkactiveemail/'+'?token='+ scret_data
            tasks.send_verify_email.delay(email,url)
        except Exception as e:
            return http.JsonResponse({'code':'-1','errmsg':'添加邮箱失败'})
        else:
            return http.JsonResponse({'code':'0','errmsg':'添加成功'})


#验证激活邮箱
class CheckActiveEmailView(View):
    #同时验证用户名和邮箱
    def get(self,request):
        #得到加密后的信息
        try:
            scret = request.GET.get('token')
            print(request.user.username)
            #解密数据
            if not scret:
                return http.HttpResponseBadRequest('缺少数据')
            data = jiajiemi().jiemi(scret)
            #获得字典后进行校验数据 ,这里的数据是想要保存邮箱的用户
            #判断和点击激活的用户是否相同
            #如果发起激活请求的用户 == 申请激活邮箱的用户（写在链接中的）
            if request.user.username != data.get('username'):
                return redirect(reverse('index'))
            #如果是相同用户,则激活用户
            else:
                request.user.email_active = True
                request.user.save()
        except Exception as e:
            print(e)
            return http.HttpResponseBadRequest('添加失败')






        return redirect(reverse('usercenter'))



#展示收货地址 /address/
class AddressView(LoginRequiredMixin,View):

    def get(self,request):
        #把地址信息取出来给网页
        addresses= Address.objects.filter(user=request.user,is_deleted=False)
        address_dict_list = []
        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }
            address_dict_list.append(address_dict)

        context = { 'default_address_id': request.user.default_address_id,
        'addresses': address_dict_list,}
        return render(request,'user_center_site.html',context)




#忘记密码
class FindPasswordView(View):

    def get(self,request):

        return render(request,'find_password.html')


#登陆界面发送短信验证码
class LoginSMSCodeView(View):

    def get(self, request,mobile):

        #多加一个判断，是否重复发送请求
        #随机生成验证码,存入数据库，便于校验
        random_sms = random.randint(1000,9999)
        print('进入登陆短信验证码：%s'%random_sms)
        #连接三号redis数据库
        sms_cli = django_redis.get_redis_connection('SMS')
        #如果数据库中存在时间标识则返回  ,存在返回1 ,不存在返回0
        # count = sms_cli.exists('%s_time_flag' % mobile)
        # if count == 1:
        #     return JsonResponse({"code1":"2",'errmsg':'短信发送过于频繁'})
        sms_cli.setex(mobile,300,random_sms)

        #判断下现在有多少人注册了
        num = models.User.objects.count()
        #因为现在只能给自己发..手机号就填自己的
        '''先注释一下'''
        # from celery_tasks.sms.tasks import ccp_send_sms_code
        # ccp_send_sms_code.delay('17689949640','%d胡加增欢迎您,恭喜您成为本站第%s个尊贵用户 ' % (random_sms,num+1))


        '''上面两句打开即可'''
        # CCP().send_template_sms('17689949640',['%d胡加增欢迎您,恭喜您成为本站第%s个尊贵用户 ' % (random_sms,num+1),5],1)
        # 发送成功在数据库多写一个时间的标识 一个手机一个标识, 前面加一个判断如果存在则返回，必须要等时间结束才可以继续注册
        sms_cli.setex('%s_time_flag' % mobile, 300, 1)
        return JsonResponse({"code1":"0",'errmsg':'短信发送成功'})


        #



#修改密码
class ChangePasswordView(View):

    def post(self,request,username):
        #接收参数
        username = username
        password = json.loads(request.body.decode()).get('password')
        password2 = json.loads(request.body.decode()).get('password2')

        #校验参数


        user = models.User.objects.get(username=username)
        user.set_password(password)

        return JsonResponse({'code1':'0'})








